package com.archive.forum.service;

import com.archive.forum.dto.NotificationDTO;
import com.archive.forum.dto.PaginationDTO;
import com.archive.forum.enums.NotificationStatusEnum;
import com.archive.forum.enums.NotificationTypeEnum;
import com.archive.forum.exception.CustomizeException;
import com.archive.forum.exception.ExceptionEnum;
import com.archive.forum.mapper.NotificationMapper;
import com.archive.forum.mapper.UserMapper;
import com.archive.forum.model.Notification;
import com.archive.forum.model.NotificationExample;
import com.archive.forum.model.User;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class NotificationService {
    @Autowired
    private NotificationMapper notificationMapper;
    @Autowired
    private UserMapper userMapper;
    //消息列表查询
    public PaginationDTO list(Integer userId, Integer page, Integer size) {
        //计算总页数
        PaginationDTO<NotificationDTO> paginationDTO = new PaginationDTO<>();
        NotificationExample notificationExample = new NotificationExample();
        notificationExample.createCriteria().andReceiverEqualTo(userId);
        Integer totalCount = (int) notificationMapper.countByExample(notificationExample);
        Integer totalPage;
        if (totalCount % size == 0) {
            totalPage= totalCount / size;
        }else{
            totalPage= totalCount / size + 1;
        }
        if(totalPage!=0){
            if (page<1){
                page=1;
            }
            if (page>totalPage){
                page=totalPage;
            }
        }
        Integer offset = size * (page - 1);
        //查询倒序排放
        NotificationExample example = new NotificationExample();
        example.setOrderByClause("gmt_create desc");
        example.createCriteria().andReceiverEqualTo(userId);
        List<Notification> notifications = notificationMapper.selectByExampleWithRowbounds(example,new RowBounds(offset,size));
        if (notifications.isEmpty()){
            return paginationDTO;
        }
        List<NotificationDTO> notificationDTOS = new ArrayList<>();
        for (Notification notification : notifications) {
            NotificationDTO notificationDTO = new NotificationDTO();
            BeanUtils.copyProperties(notification,notificationDTO);
            notificationDTO.setTypeName(NotificationTypeEnum.nameOfType(notification.getType()));
            notificationDTOS.add(notificationDTO);
        }
        paginationDTO.setPagination(page, totalPage);
        paginationDTO.setData(notificationDTOS);
        return paginationDTO;
    }
    //未读消息记数
    public Integer unreadCount(Integer userId) {
        NotificationExample example = new NotificationExample();
        example.createCriteria()
                .andReceiverEqualTo(userId)
                .andStatusEqualTo(NotificationStatusEnum.UNREAD.getStatus());
        return Math.toIntExact(notificationMapper.countByExample(example));
    }
    //完成已读
    public NotificationDTO read(Integer id, User user) {
        Notification notification = notificationMapper.selectByPrimaryKey(id);
        if (notification == null) {
            throw new CustomizeException(ExceptionEnum.NOTIFICATION_NOT_FOUND);
        }
        if (!Objects.equals(notification.getReceiver(), user.getId())) {
            throw new CustomizeException(ExceptionEnum.READ_NOTIFICATION_FAIL);
        }
        notification.setStatus(NotificationStatusEnum.READ.getStatus());
        notificationMapper.updateByPrimaryKey(notification);
        NotificationDTO notificationDTO = new NotificationDTO();
        BeanUtils.copyProperties(notification,notificationDTO);
        notificationDTO.setTypeName(NotificationTypeEnum.nameOfType(notification.getType()));
        return notificationDTO;
    }
    //全部已读
    @Transactional
    public void markAsRead(Integer userId) {
        NotificationExample example = new NotificationExample();
        example.createCriteria().andReceiverEqualTo(userId);
        List<Notification> notifications = notificationMapper.selectByExample(example);
        for (Notification notification : notifications) {
            notification.setStatus( NotificationStatusEnum.READ.getStatus());
            notificationMapper.updateByPrimaryKey(notification);
        }
    }
    //全部清除
    @Transactional
    public void deleteAllNotifications(Integer userId) {
        NotificationExample example = new NotificationExample();
        example.createCriteria()
                .andReceiverEqualTo(userId);

        notificationMapper.deleteByExample(example);
    }
}
